package cn.tedu.jxc.service.impl;

import cn.tedu.jxc.ex.ServiceException;
import cn.tedu.jxc.mapper.UserMapper;
import cn.tedu.jxc.mapper.UserRoleMapper;
import cn.tedu.jxc.pojo.dto.UserDTO;
import cn.tedu.jxc.pojo.dto.UserInsertDTO;
import cn.tedu.jxc.pojo.dto.UserUpdateDTO;
import cn.tedu.jxc.pojo.entity.User;
import cn.tedu.jxc.pojo.entity.UserRole;
import cn.tedu.jxc.pojo.vo.UserStandardVO;
import cn.tedu.jxc.pojo.vo.UserVO;
import cn.tedu.jxc.repo.UserRedisRepository;
import cn.tedu.jxc.security.AdminDetails;
import cn.tedu.jxc.service.UserService;
import cn.tedu.jxc.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserRedisRepository userRedisRepository;

    @Autowired
    private AuthenticationManager authenticationManager;


    @Override
    public String login(UserDTO userDTO) {

        Authentication authentication = new UsernamePasswordAuthenticationToken(
                userDTO.getUsername(),userDTO.getPassword());
        Authentication authenticateResult = authenticationManager.authenticate(authentication);

        Object principal = authenticateResult.getPrincipal();
        AdminDetails adminDetails = (AdminDetails) principal;
        String username=adminDetails.getUsername();
        Integer id = adminDetails.getId();
        //权限
        Collection<GrantedAuthority> authorities = adminDetails.getAuthorities();
        String authoritiesJsonString = JSON.toJSONString(authorities);
        //信息
        String secretKey = "GJHkjasnl78";
        Map<String,Object> claims = new HashMap<>();
        claims.put("username",username);
        claims.put("id",id);
        claims.put("authoritiesJsonString",authoritiesJsonString);
        Date date = new Date(System.currentTimeMillis()+10*24*60*60*1000L);
        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("生成的JWT：{}", jwt);
        return jwt;


    }

        /**
     * 获取用户列表
     * @param
     * @param size
     * @return
     */
    @Override
    public List<UserStandardVO> list(int page, int size) {
        int index =(page-1)*size;
        Long start = (long) index;
        Long end = (long)index+size-1;
        return userRedisRepository.getListRange(start,end);
    }

    /**
     * 统计用户表数据总条数
     * @return
     */
    @Override
    public int count() {
        return userMapper.selectCount();
    }

    /**
     * 根据id删除
     * @param id
     */
    @Override
    public void deleteById(Integer id) {
        log.debug("开始处理删除业务!");
        if (id == 1) {
            String message = "删除用户失败，尝试删除的数据不存在！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        UserStandardVO userStandardVO = userMapper.selectById(id);
        if (userStandardVO == null) {
            String message="删除失败,用户不存在!";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        int row = userMapper.deleteById(id);
        if (row!=1){
            String message ="删除失败,服务器忙,稍后再试!";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,message );
        }
        log.debug("删除成功!");
        userRoleMapper.deleteByUserId(id);
    }

    /**
     * 添加新管理员
     * @param userInsertDTO
     */
    @Override
    public void addNew(UserInsertDTO userInsertDTO) {
        int count = userMapper.countByUsername(userInsertDTO.getUsername());
        if (count>0){
            String message = "添加失败,用户名已存在";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }
        //将密码加密存到数据库
        String password = userInsertDTO.getPassword();
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(password);
        userInsertDTO.setPassword(encode);
        User user = new User();
        BeanUtils.copyProperties(userInsertDTO,user);
        int row = userMapper.insert(user);
        if (row!=1){
            String message ="添加失败,服务器忙,稍后再试!";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,message );
        }
        log.debug("添加成功!");
        //往user_role表插数据
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(userInsertDTO.getRoleId());

        int rows = userRoleMapper.inserts(userRole);
        if (rows!=1){
            String message ="添加失败,服务器忙,稍后再试!";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,message );
        }
        log.debug("角色用户表添加成功!");
    }

    /**
     * 获取修改列表数据
     * @param id
     * @return
     */
    @Override
    public UserStandardVO selectById(Integer id) {
        UserStandardVO userStandardVO = userMapper.selectById(id);
        if (userStandardVO == null) {
            String message="获取数据失败,用户不存在!";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        return userStandardVO;
    }

    /**
     * 修改用户信息
     * @param userUpdateDTO
     */
    @Override
    public void updateUser(UserUpdateDTO userUpdateDTO) {
        UserStandardVO userStandardVO = userMapper.selectById(userUpdateDTO.getId());
        if (userStandardVO==null){
            String message = "修改失败,用户名不存在";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(userUpdateDTO.getPassword());
        userUpdateDTO.setPassword(encode);
        User user = new User();
        BeanUtils.copyProperties(userUpdateDTO,user);
        int row = userMapper.update(user);
        if (row!=1){
            String message ="修改失败,服务器忙,稍后再试!";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,message );
        }
        log.debug("修改成功!");

        UserRole userRole = new UserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(userUpdateDTO.getRoleId());
        int rows = userRoleMapper.update(userRole);
        if (rows!=1){
            String message ="添加失败,服务器忙,稍后再试!";
            log.debug(message);
            throw  new ServiceException(ServiceCode.ERR_CONFLICT,message );
        }
        log.debug("角色iu该成功!");
    }

    /**
     * 搜索用户
     * @param username
     * @param index
     * @param size
     * @return
     */
    @Override
    public List<UserStandardVO> search(String username,int index, int size) {
        log.debug("开始搜索用户");
        return userMapper.selectByUsername(username,index,size);
    }

    /**
     * 启用管理员
     * @param id
     */
    @Override
    public void enable(Integer id) {
        enableDisable(id,1);
    }
    /**
     * 禁用管理员
     * @param id
     */
    @Override
    public void disable(Integer id) {
        enableDisable(id,0);
    }

    @Override
    public void rebuildUserCache() {
        userRedisRepository.deleteAll();
        List<UserStandardVO> list = userMapper.getList();
        userRedisRepository.saveList(list);
        log.debug("将管理员详情写入到Redis缓存，完成{}！");
    }

    /**
     * 启用禁用操作
     * @param id
     * @param enable
     */
    private void enableDisable(Integer id,Integer enable){
        String[] tips = {"禁用", "启用"};
        log.debug("开始处理【{}管理员】的业务，参数：{}", tips[enable], id);

        UserStandardVO userStandardVO = userMapper.selectById(id);
        if (userStandardVO == null) {
            String message = tips[enable] + "管理员失败，尝试访问的数据不存在！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        if (userStandardVO.getEnable().equals(enable)) {
            String message = tips[enable] + "管理员失败，管理员账号已经处于" + tips[enable] + "状态！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        User user = new User();
        user.setId(id);
        user.setEnable(enable);
        int rows = userMapper.update(user);
        if (rows != 1) {
            String message = tips[enable] + "管理员失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }
}
